#!/usr/bin/env python

import gtk
import math
import copy
import cairo

class VisualiseWidget(gtk.DrawingArea):
	
	frame_id = 0
	
	def __init__(self):
		gtk.gdk.threads_init()
		
		gtk.DrawingArea.__init__(self)
		self.set_size_request(800, 600)
		
		self.connect("expose_event", self.expose)
		
		self.add_events(gtk.gdk.POINTER_MOTION_MASK |
						gtk.gdk.BUTTON_PRESS_MASK |
						gtk.gdk.ENTER_NOTIFY_MASK |
						gtk.gdk.LEAVE_NOTIFY_MASK)
		self.connect("button_press_event", self.mouse_button)
		self.connect("motion-notify-event", self.mouse_move)
		self.connect("scroll-event", self.scroll_event)
		self.connect("enter-notify-event", self.mouse_move)
		self.connect("leave-notify-event", self.mouse_move)
		
		self.reset()
	
	def reset(self):
		self.mouse_is_over = False
		self.mouse_position = (0, 0)		
		self.scale = 200.0
		self.zoom = 20000.0
		self.center = (1.5, -1.0)
		self.robot = None
		
	def mouse_move(self, widget, event):
		if event.type == gtk.gdk.ENTER_NOTIFY:
			self.mouse_is_over = True
		elif event.type == gtk.gdk.LEAVE_NOTIFY:
			self.mouse_is_over = False
		
		# Calculate the mouse position in pixels of the original image
		rect = self.get_allocation()
		self.mouse_position = \
		 ((event.x - 0.5 * rect.width) / self.scale + self.center[0],
		  (event.y - 0.5 * rect.height) / self.scale + self.center[1])
			
		#if self.mouse_is_over == True:
		#	self.queue_draw()
	
	def mouse_button(self, widget, event):
		if event.button == 1:
			#print "left click"
			pass
		elif event.button == 2:
			#print "middle click"
			pass
		elif event.button == 3:
			#print "right click"
			pass
		elif event.button == 4:
			print "button 4"
		elif event.button == 5:
			print "button 5"
		elif event.button == 6:
			print "other button"
		
		return False
		
	def expose(self, widget, event):		
	
		cr = self.window.cairo_create()
		
		# Restrict Cairo to the exposed area; avoid extra work
		cr.rectangle(event.area.x, event.area.y,
					 event.area.width, event.area.height)
		cr.clip()
		
		# Fill the background with gray
		cr.set_source_rgb(0.9, 0.9, 0.9)
		w, h = self.window.get_size()
		cr.rectangle(0, 0, w, h)
		cr.fill()
		
		self.draw(cr)
		
		cr.get_target().write_to_png("movie/bild_%04d.png" % self.frame_id)
		self.frame_id += 1
	
	def scroll_event(self, widget, event):
		if event.direction == gtk.gdk.SCROLL_UP:
			self.zoom *= 1.05
		elif event.direction == gtk.gdk.SCROLL_DOWN:
			self.zoom /= 1.05
		
		self.set_zoom(self.zoom)
	
	def set_zoom(self, zoom):
		rel = self.scale / (zoom/100.0)		
		if self.mouse_is_over:
			self.center = (self.mouse_position[0] - rel * (self.mouse_position[0] - self.center[0]), 
						   self.mouse_position[1] - rel * (self.mouse_position[1] - self.center[1]))
		self.scale = zoom / 100.0
		self.queue_draw()
		
	def draw(self, context):
		# Window size
		rect = self.get_allocation()
		
		# Visible area in meters
		w, h = 3.0, 2.0

		context.translate(rect.width/2.0-self.center[0]*self.scale,
						  rect.height/2.0-self.center[1]*self.scale)
		context.scale(self.scale, self.scale)
		#context.set_source_surface(self.bg_surface)
		#context.rectangle(0,0,w,h)
		#context.fill()
		
		
		if self.simulator != None:
			self.simulator.draw(context)

	def redraw(self):
		self.queue_draw()
		

		

def main():
	window = gtk.Window()
	vw = VisualiseWidget()

	window.add(vw)
	window.connect("destroy", gtk.main_quit)
	window.show_all()

	from simulator import Simulator
	from environment import Environment
	from robot import Robot
	from brain import Brain
	robot = Robot(Brain())
	environment = Environment()
	sim = Simulator(robot, environment)
	vw.simulator = sim

	from timer import SimStepper
	c = SimStepper()
	c.functions.append(sim.step)
	c.functions.append(vw.redraw)
	c.start()
	
	gtk.main()
	
	c.stop()
	
    
if __name__ == "__main__":
    main()
